home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 April: Mac OS SDK / Dev.CD Apr 00 SDK1.toast / Development Kits / Mac OS / ColorSync 3.0 Mac SDK / Sample Code / ProfileRenamer / DSUserProcs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-28  |  14.0 KB  |  506 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2. **
  3. **  Project Name:    DropShell
  4. **     File Name:    DSUserProcs.c
  5. **
  6. **   Description:    Specific AppleEvent handlers used by the DropBox
  7. **
  8. *******************************************************************************
  9. **                       A U T H O R   I D E N T I T Y
  10. *******************************************************************************
  11. **
  12. **    Initials    Name
  13. **    --------    -----------------------------------------------
  14. **    LDR            Leonard Rosenthol
  15. **    MTC            Marshall Clow
  16. **    SCS            Stephan Somogyi
  17. **
  18. *******************************************************************************
  19. **                      R E V I S I O N   H I S T O R Y
  20. *******************************************************************************
  21. **
  22. **      Date        Time    Author    Description
  23. **    --------    -----    ------    ---------------------------------------------
  24. **    06/23/94            LDR        Added support for ProcessItem and ProcessFolder handling
  25. **    02/20/94            LDR        Modified Preflight & Postflight to take item count
  26. **    01/25/92            LDR        Removed the use of const on the userDataHandle
  27. **    12/09/91            LDR        Added the new SelectFile userProc
  28. **                                Added the new Install & DisposeUserGlobals procs
  29. **                                Modified PostFlight to only autoquit on odoc, not pdoc
  30. **    11/24/91            LDR        Added the userProcs for pdoc handler
  31. **                                Cleaned up the placement of braces
  32. **                                Added the passing of a userDataHandle
  33. **    10/29/91            SCS        Changes for THINK C 5
  34. **    10/28/91            LDR        Officially renamed DropShell (from QuickShell)
  35. **                                Added a bunch of comments for clarification
  36. **    10/06/91    00:02    MTC        Converted to MPW C
  37. **    04/09/91    00:02    LDR        Added to Projector
  38. **
  39. ******************************************************************************/
  40.  
  41. #include <Types.h>
  42. #include <TextUtils.h>
  43. #include <StandardFile.h>
  44. #include <CMApplication.h>
  45. #include <Sound.h>
  46.  
  47. #include "DSUserProcs.h"
  48.  
  49. // Static Prototypes
  50. static OSErr ProcessItem    ( FSSpecPtr myFSSPtr);
  51. static OSErr ProcessFolder  ( FSSpecPtr myFSSPtr);
  52. static OSErr ProcessProfile ( FSSpecPtr myFSSPtr);
  53.  
  54. static CMError    SetScriptProfileDescription ( CMProfileRef prof,
  55.                                               Str255 name, ScriptCode code);
  56. static char* Pstrcpy2C (char *dst, ConstStr255Param src, const unsigned char dstLen );
  57.  
  58.  
  59. /*
  60.     This routine is called during init time.
  61.     
  62.     It allows you to install more AEVT Handlers beyond the standard four
  63. */
  64. #pragma segment Main
  65. void InstallOtherEvents (void)
  66. {
  67. }
  68.  
  69.  
  70. /*    
  71.     This routine is called when an OAPP event is received.
  72.     
  73.     Currently, all it does is set the gOApped flag, so you know that
  74.     you were called initally with no docs, and therefore you shouldn't 
  75.     quit when done processing any following odocs.
  76. */
  77. #pragma segment Main
  78. void OpenApp (void)
  79. {
  80.     gOApped = true;
  81. }
  82.  
  83.  
  84. /*    
  85.     This routine is called when an QUIT event is received.
  86.     
  87.     We simply set the global done flag so that the main event loop can
  88.     gracefully exit.  We DO NOT call ExitToShell for two reasons:
  89.     1) It is a pretty ugly thing to do, but more importantly
  90.     2) The Apple event manager will get REAL upset!
  91. */
  92. #pragma segment Main
  93. void QuitApp (void)
  94. {
  95.     gDone = true;    /*    All Done! */
  96. }
  97.  
  98.  
  99. /*    
  100.     This routine is the first one called when an ODOC or PDOC event is received.
  101.     
  102.     In this routine you would place code used to setup structures, etc. 
  103.     which would be used in a 'for all docs' situation (like "Archive all
  104.     dropped files")
  105.  
  106.     Obviously, the opening boolean tells you whether you should be opening
  107.     or printing these files based on the type of event recieved.
  108.     
  109.     NEW IN 2.0!
  110.     The itemCount parameter is simply the number of items that were dropped on
  111.     the application and that you will be processing.  This gives you the ability
  112.     to do a single preflight for memory allocation needs, rather than doing it
  113.     once for each item as in previous versions.
  114.     
  115.     userDataHandle is a handle that you can create & use to store your own
  116.     data structs.  This dataHandle will be passed around to the other 
  117.     odoc/pdoc routines so that you can get at your data without using
  118.     globals - just like the new StandardFile.  
  119.     
  120.     We also return a boolean to tell the caller if you support this type
  121.     of event.  By default, our dropboxes don't support the pdoc, so when
  122.     opening is FALSE, we return FALSE to let the caller send back the
  123.     proper error code to the AEManager.
  124.  
  125.     You will probably want to remove the #pragma unused (currently there to fool the compiler!)
  126. */
  127. #pragma segment Main
  128. Boolean PreFlightDocs (Boolean opening, short itemCount, Handle *userDataHandle)
  129. {
  130. #pragma unused ( itemCount, userDataHandle )
  131.  
  132.     return opening;        // we support opening, but not printing - see above
  133. }
  134.  
  135.  
  136. /*    
  137.     This routine is called for each file passed in the ODOC event.
  138.     
  139.     In this routine you would place code for processing each file/folder/disk that
  140.     was dropped on top of you.
  141.     
  142.     You will probably want to remove the #pragma unused (currently there to fool the compiler!)
  143. */
  144. #pragma segment Main
  145. void OpenDoc ( FSSpecPtr myFSSPtr, Boolean opening, Handle userDataHandle )
  146. {
  147. #pragma unused ( opening, userDataHandle )
  148.     OSErr    err = noErr;
  149.     
  150.     
  151.     #ifdef qWalkFolders
  152.     /*
  153.         For this case we need to determine if the FSSpec is a file or folder.
  154.         If it's a folder, we then need to process each item in that folder,
  155.         otherwise just process the item.
  156.     */
  157.     if (FSpIsFolder(myFSSPtr))
  158.         err = ProcessFolder(myFSSPtr);
  159.     else
  160.         err = ProcessItem(myFSSPtr);
  161.     #else
  162.     /*
  163.         For this case we just call ProcessItem on the FSSpec above.
  164.     */
  165.     err = ProcessItem(myFSSPtr);
  166.     #endif
  167.     
  168.     // you should probably do something if you get back an error ;)
  169. }
  170.  
  171.  
  172. /*    
  173.     This routine is the last routine called as part of an ODOC event.
  174.     
  175.     In this routine you would place code to process any structures, etc. 
  176.     that you setup in the PreflightDocs routine.
  177.  
  178.     NEW IN 2.0!
  179.     The itemCount parameter was the number of items that you processed.
  180.     It is passed here just in case you need it ;)  
  181.     
  182.     If you created a userDataHandle in the PreFlightDocs routines, this is
  183.     the place to dispose of it since the Shell will NOT do it for you!
  184.     
  185.     You will probably want to remove the #pragma unusued (currently there to fool the compiler!)
  186. */
  187. #pragma segment Main
  188. void PostFlightDocs ( Boolean opening, short itemCount, Handle userDataHandle )
  189. {
  190. #pragma unused ( itemCount, userDataHandle )
  191.  
  192.     if ( (opening) && (!gOApped) )
  193.         gDone = true;    //    close everything up!
  194.  
  195.     /*
  196.         The reason we do not auto quit is based on a recommendation in the
  197.         Apple event Registry which specifically states that you should NOT
  198.         quit on a 'pdoc' as the Finder will send you a 'quit' when it is 
  199.         ready for you to do so.
  200.     */
  201. }
  202.  
  203.  
  204. /*
  205.     This routine is called during the program's initialization and gives you
  206.     a chance to allocate or initialize any of your own globals that your
  207.     dropbox needs.
  208.     
  209.     You return a boolean value which determines if you were successful.
  210.     Returning false will cause DropShell to exit immediately.
  211. */
  212. Boolean InitUserGlobals(void)
  213. {
  214.     return true;    // nothing to do, we must be successful!
  215. }
  216.  
  217.  
  218. /*
  219.     This routine is called during the program's cleanup and gives you
  220.     a chance to deallocate any of your own globals that you allocated 
  221.     in the above routine.
  222. */
  223. void DisposeUserGlobals(void)
  224. {
  225.     // nothing to do for our sample dropbox
  226. }
  227.  
  228.  
  229. #pragma mark -
  230.  
  231.  
  232. /*
  233.     This routine gets called for each item (which could be either a file or a folder)
  234.     that the caller wants dropped.  The determining factor is the definition of the 
  235.     qWalkFolder compiler directive.   Either way, the item in question should be
  236.     processed as a single item and not "dissected" into component units (like subfiles
  237.     of a folder!)
  238. */
  239. static OSErr ProcessItem (FSSpecPtr myFSSPtr)
  240. {
  241.     return ProcessProfile(myFSSPtr);
  242. }
  243.  
  244.  
  245. /*
  246.     This routine gets called for any folder (or disk) that the caller wants 
  247.     processed as a set of component items, instead of as a single entity.
  248.     The determining factor is the definition of the qWalkFolder compiler directive.
  249. */
  250. static OSErr ProcessFolder (FSSpecPtr myFSSPtr)
  251. {
  252.     OSErr        err = noErr;
  253.     short        index, oldIndex, localIndex;
  254.     FSSpec        localFSSpec, curFSSpec;
  255.     CInfoPBRec    cipb;
  256.     Str255        fName, vFName;
  257.     long        dirID, origDirID;
  258.     Boolean        foundPosition;
  259.  
  260.      // copy the source locally to avoid recursion problems
  261.      BlockMoveData(myFSSPtr, &localFSSpec, sizeof(FSSpec));
  262.      
  263.     //    get the dirID for THIS folder, not it's parent!
  264.     BlockMoveData(localFSSpec.name, fName, 32);
  265.     
  266.     cipb.hFileInfo.ioCompletion    = 0L;
  267.     cipb.hFileInfo.ioNamePtr    = fName;
  268.     cipb.hFileInfo.ioVRefNum    = localFSSpec.vRefNum;
  269.     cipb.hFileInfo.ioFDirIndex    = 0;    // use the dir & vRefNum;
  270.     cipb.hFileInfo.ioDirID        = localFSSpec.parID;
  271.     err = PBGetCatInfoSync(&cipb);
  272.     
  273.     if (!err)
  274.     {        
  275.         origDirID = cipb.dirInfo.ioDrDirID; // copy the sucker
  276.         index = 1;
  277.                 
  278.         // index through all contents of this folder
  279.         while (err == noErr)
  280.         {
  281.             dirID = origDirID;
  282.             localIndex = index;
  283.             fName [0] = 0;
  284.             cipb.hFileInfo.ioCompletion    = 0L;
  285.             cipb.hFileInfo.ioNamePtr    = fName;
  286.             cipb.hFileInfo.ioVRefNum    = localFSSpec.vRefNum;
  287.             cipb.hFileInfo.ioFDirIndex    = localIndex;    // use a real index
  288.             cipb.hFileInfo.ioDirID        = dirID;
  289.             err = PBGetCatInfoSync(&cipb);
  290.  
  291.             if (!err)
  292.             {
  293.                 BlockMoveData(fName, curFSSpec.name, 32);
  294.                 curFSSpec.vRefNum    = cipb.hFileInfo.ioVRefNum;
  295.                 curFSSpec.parID        = dirID;
  296.             
  297.                 /*    
  298.                     Check to see if this entry is a folder.
  299.                 */
  300.                 if (cipb.hFileInfo.ioFlAttrib & ioDirMask)
  301.                     err = ProcessFolder(&curFSSpec);
  302.                 else
  303.                 {
  304.                     if (gTypeListCount == -1)
  305.                         err = ProcessItem(&curFSSpec);
  306.                     else
  307.                     {
  308.                         short i;
  309.                         for (i=0; i<gTypeListCount; i++)
  310.                             if (gTypeList[i] == cipb.hFileInfo.ioFlFndrInfo.fdType)
  311.                                 err = ProcessItem(&curFSSpec);
  312.                     }
  313.                 }    
  314.             
  315.                 /*    If we've had an error, get out! */
  316.                 if (err)    break;
  317.  
  318.                 // dirID = origDirID;    
  319.                 localIndex = index;    
  320.  
  321.                 /*    
  322.                     Now take into account new files being created
  323.                     in the current directory & messing up our index.
  324.                     See Dev.CD Vol. XI:Tools & Apps (Moof!):Misc Utilities:
  325.                     Disinfectant & Source 2.5.1:Sample:Notes:Scan Alg    
  326.                 */
  327.                 vFName [0] = 0;
  328.                 cipb.hFileInfo.ioCompletion    = 0L;
  329.                 cipb.hFileInfo.ioNamePtr    = vFName;
  330.                 cipb.hFileInfo.ioVRefNum    = localFSSpec.vRefNum;
  331.                 cipb.hFileInfo.ioFDirIndex    = localIndex;    // use a real index
  332.                 cipb.hFileInfo.ioDirID        = dirID;
  333.                 err = PBGetCatInfoSync(&cipb);
  334.                 oldIndex = index;
  335.                 if (!err)
  336.                 {
  337.                     /*    If they're equal - same place, go to next */
  338.                     if (EqualString (vFName, fName, false, false))
  339.                         index++;
  340.                 }
  341.                 
  342.                 /*    If we didn't advance, then perhaps a file was created or deleted */
  343.                 if (oldIndex == index)
  344.                 {
  345.                     oldIndex        = index;    /* save off the old */
  346.                     index            = 0;        /* and start at the beginning */
  347.                     err                = noErr;
  348.                     vFName [0]        = 0;
  349.                     foundPosition    = false;
  350.                     
  351.                     while (!foundPosition)
  352.                     {
  353.                         index++;
  354.                         vFName [0] = 0;
  355.                         cipb.hFileInfo.ioCompletion    = 0L;
  356.                         cipb.hFileInfo.ioNamePtr    = vFName;
  357.                         cipb.hFileInfo.ioVRefNum    = localFSSpec.vRefNum;
  358.                         cipb.hFileInfo.ioFDirIndex    = index;    /* now use a real index */
  359.                         cipb.hFileInfo.ioDirID        = dirID;
  360.                         err = PBGetCatInfoSync(&cipb);
  361.                         
  362.                         if (err == fnfErr)  // we've just been deleted
  363.                         {
  364.                             index = oldIndex;
  365.                             foundPosition = true;
  366.                             err = noErr;    // have to remember to reset this!
  367.                         }
  368.                         
  369.                     /*    found same file & same index position */
  370.                     /*    so try the next item */
  371.                         if ((!foundPosition) && EqualString(fName, vFName, false, false))
  372.                         {
  373.                             index++;
  374.                             foundPosition = true;
  375.                         }
  376.                     }
  377.                 }
  378.             }
  379.         }
  380.     }
  381.     return err;
  382. }
  383.  
  384.  
  385. static OSErr ProcessProfile ( FSSpecPtr myFSSPtr)
  386. {
  387.     OSErr                    err = noErr;
  388.     CMProfileLocation        profLoc;
  389.     CMProfileRef            prof = nil;
  390.     
  391.     profLoc.locType = cmFileBasedProfile;
  392.     profLoc.u.fileLoc.spec = *myFSSPtr;
  393.     
  394.     err = CMOpenProfile( &prof, &profLoc );
  395.     if (err) goto bail;
  396.     
  397.     err = SetScriptProfileDescription( prof, profLoc.u.fileLoc.spec.name, 0);
  398.     if (err) goto bail;
  399.     
  400.     err = CMUpdateProfile( prof );
  401.     if (err) goto bail;
  402.     
  403. bail:
  404.     
  405.     if (prof) err = CMCloseProfile(prof);
  406.     
  407.     return err;
  408. }
  409.  
  410.  
  411. #pragma mark -
  412.  
  413.  
  414. /******************************************************************************/
  415. static CMError SetScriptProfileDescription ( CMProfileRef prof, Str255 name, ScriptCode code)
  416. {
  417.     CMError        err;
  418.     UInt32        size;
  419.     Ptr            tag;
  420.     UInt32        offset;
  421.     UInt32        aNL;                        /* ascii name length */
  422.     UInt32        sNL;                        /* mac script name length */
  423.     UInt32        uNL;                        /* unicode name length */
  424.     
  425. //    4    OSType             typeDescriptor;        /* cmSigProfileDescriptionType */
  426. //    4    UInt32             reserved;            /* fill with 0x00 */
  427. //    4    UInt32             ASCIICount;            /* count of 1 byte characters */
  428. //    aNL    unsigned char     ASCIIName[2];        /* Variable size*/
  429. //    4    UInt32             UniCodeCode;
  430. //    4    UInt32             UniCodeCount;        /* count of 2 byte characters */
  431. //    uNL    unsigned char     UniCodeName[2];        /* Variable size */
  432. //    2    short             ScriptCodeCode;
  433. //    1    unsigned char     ScriptCodeCount;    /* count of 1 byte characters */
  434. //    sNL    unsigned char     ScriptCodeName[2];    /* Variable size */
  435.  
  436.     offset = 0;
  437.     aNL = sNL = name[0]+1;
  438.     uNL = 0;
  439.     size = 23 + aNL + uNL + sNL;
  440.     tag = NewPtrClear( size );
  441.     if (!tag) return memFullErr;
  442.     
  443.     // OSType  tag.typeDescriptor
  444.     *((OSType*)(tag+offset)) = cmSigProfileDescriptionType;
  445.     offset += 4;
  446.     
  447.     // UInt32  tag.reserved
  448.     offset += 4;
  449.  
  450.     // UInt32  tag.ASCIICount
  451.     *((UInt32*)(tag+offset)) = aNL;
  452.     offset += 4;
  453.     
  454.     // tag.ASCIIName
  455.     if (aNL)
  456.         Pstrcpy2C(tag+offset, name, 255 );
  457.     offset += aNL;
  458.     
  459.     // UInt32  tag.UniCodeCode
  460.     *((UInt32*)(tag+offset)) = 0;
  461.     offset += 4;
  462.     
  463.     // UInt32  tag.UniCodeCount
  464.     *((UInt32*)(tag+offset)) = uNL;
  465.     offset += 4;
  466.     
  467.     // tag.UniCodeName
  468.     if (uNL)
  469.         {}
  470.     offset += uNL;
  471.     
  472.     // tag.ScriptCodeCode
  473.     *((SInt16*)(tag+offset)) = code;
  474.     offset += 2;
  475.     
  476.     // tag.ScriptCodeCount
  477.     *((UInt8*)(tag+offset)) = uNL;
  478.     offset += 1;
  479.     
  480.     // tag.ScriptCodeName
  481.     if (sNL)
  482.         Pstrcpy2C(tag+offset, name, 255 );
  483.     offset += sNL;
  484.     
  485.     err = CMSetProfileElement(prof, cmSigProfileDescriptionType, GetPtrSize(tag), tag);
  486.     
  487.     DisposePtr(tag);
  488.     return err;
  489. }
  490.  
  491.  
  492. static char* Pstrcpy2C (char *dst, ConstStr255Param src, const unsigned char dstLen )
  493. {
  494.     unsigned char bytesToCopy ;
  495.     
  496.     bytesToCopy = *src ;
  497.     if (bytesToCopy > dstLen)                    // make sure were not too big
  498.         bytesToCopy = dstLen ;
  499.         
  500.     BlockMoveData(    src + 1, dst,
  501.                     bytesToCopy ) ;                // copy string in
  502.     dst[bytesToCopy] = 0 ;                        // terminate c-string
  503.     
  504.     return dst ;
  505. }
  506.